package org.beetl.sql.clazz;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.beetl.sql.annotation.entity.ResultProvider;
import org.beetl.sql.annotation.entity.RowProvider;
import org.beetl.sql.clazz.ClassAnnotation;
import org.beetl.sql.clazz.kit.CaseInsensitiveHashMap;
import org.beetl.sql.clazz.kit.DefaultCache;
import org.beetl.sql.core.BeetlSQLException;
import org.beetl.sql.core.annotatoin.AssignID;
import org.beetl.sql.core.annotatoin.AutoID;
import org.beetl.sql.core.annotatoin.Builder;
import org.beetl.sql.core.annotatoin.Column;
import org.beetl.sql.core.annotatoin.ColumnIgnore;
import org.beetl.sql.core.annotatoin.InsertIgnore;
import org.beetl.sql.core.annotatoin.LogicDelete;
import org.beetl.sql.core.annotatoin.SeqID;
import org.beetl.sql.core.annotatoin.Table;
import org.beetl.sql.core.annotatoin.UpdateIgnore;
import org.beetl.sql.core.annotatoin.Version;
import org.beetl.sql.core.annotatoin.builder.AttributeBuilderHolder;
import org.beetl.sql.core.annotatoin.builder.ObjectBuilderHolder;
import org.beetl.sql.core.annotatoin.builder.ObjectPersistBuilder;
import org.beetl.sql.core.annotatoin.builder.ObjectSelectBuilder;
import org.beetl.sql.core.kit.BeanKit;

//import net.bytebuddy.ByteBuddy;
//import net.bytebuddy.description.annotation.AnnotationDescription;
//import net.bytebuddy.dynamic.DynamicType;
//import net.bytebuddy.matcher.ElementMatchers;

public class LegacyClassAnnotation extends org.beetl.sql.clazz.ClassAnnotation {

	// 类对应的处理类，可以多个
	private List<ObjectBuilderHolder> objectBuilders = new ArrayList<ObjectBuilderHolder>();

	// 属性对应的处理类,TODO优化，设置为null，否则jdk6有一定损耗
	private CaseInsensitiveHashMap<String, AttributeBuilderHolder> colHandlers = new CaseInsensitiveHashMap<String, AttributeBuilderHolder>();

//	private static final Map<Class, Class> modifiedClasses = new ConcurrentHashMap<>();
//	private static final Set<Class> clzSet = new HashSet<>();

//	private static DefaultCache<Class, LegacyClassAnnotation> cache = new DefaultCache<>();
	
//	private static boolean isModified = false;//防止重复动态修改javabean属性

	public static ClassAnnotation getClassAnnotation(Class entity) {
		ClassAnnotation ca = cache.get(entity);
		if (ca != null) {
			return ca;
		}
//		Class clz = modifiedClasses.get(entity);
//		if (clz != null) {
//			entity = clz;
//		}
		
		ca = new LegacyClassAnnotation(entity);
		ca.init();
		cache.put(entity, ca);
		return ca;
	}

	protected LegacyClassAnnotation(Class entityClass) {
		super(entityClass);
	}

	@Override
	protected void init() {
		Class entityClass = getEntityClass();
		if (BeanKit.isJavaClass(entityClass)) {
			return;
		}
		/* 检查映射相关注解 */
		mappingCheck();
		typeCheck();
		propertyCheck();
	}

	/**
	 * 该实体自定义的映射方式
	 * 
	 * @see ResultProvider
	 * @see RowProvider
	 */
	protected void mappingCheck() {
		Class entityClass = getEntityClass();
		/* 映射表的注解 */
		Table table = BeanKit.getAnnotation(entityClass, Table.class);
		if (table != null) {
			setTableName(table.name());
		}
	}

	protected void typeCheck() {
		Class entityClass = getEntityClass();
		Annotation[] ans = entityClass.getAnnotations();
		List<ObjectBuilderHolder> list = new ArrayList<ObjectBuilderHolder>();
		for (Annotation an : ans) {
			Builder builder = an.annotationType().getAnnotation(Builder.class);
			if (builder == null) {
				continue;
			}
			Class clz = builder.value();
			Object obj = BeanKit.newInstance(clz);
			if (!(obj instanceof ObjectPersistBuilder || obj instanceof ObjectSelectBuilder)) {
				throw new BeetlSQLException(BeetlSQLException.ANNOTATION_DEFINE_ERROR,
						entityClass + " 的注解 " + an + "  的value值必须是 BaseObjectBuilder子类");
			}
			ObjectBuilderHolder holder = new ObjectBuilderHolder(an, builder);
			list.add(holder);

		}
		objectBuilders.addAll(list);
	}

	protected void propertyCheck() {
		Class entityClass = getEntityClass();
		PropertyDescriptor[] ps = super.getPropertyDescriptor(entityClass);

		Set<String> attrInsertIgnores = super.getAttrInsertIgnores();
		Set<String> attrUpdateIgnores = super.getAttrUpdateIgnores();
		Map<String, String> attrAnnotationName = super.getAttrAnnotationName();
		CaseInsensitiveHashMap<String, String> colAnnotationName = super.getColAnnotationName();
		String autoIdAttr = super.getAutoIdAttr();
		String seqIdAttr = super.getSeqIdAttr();

		Map<String, AssignID> colAssignID = new HashMap<>();

		for (PropertyDescriptor p : ps) {
			Method readMethod = p.getReadMethod();
			Class type = p.getPropertyType();
			String attr = p.getName();
			// 各种内置注解
			ColumnIgnore sqlIgnore = BeanKit.getAnnoation(entityClass, attr, readMethod, ColumnIgnore.class);
			if (sqlIgnore != null) {
				checkAttrInsertIgnores();
				attrInsertIgnores.add(attr);
				checkAttrUpdateIgnores();
				attrUpdateIgnores.add(attr);
			}

			InsertIgnore ig = BeanKit.getAnnoation(entityClass, attr, readMethod, InsertIgnore.class);
			if (ig != null) {
				checkAttrInsertIgnores();
				attrInsertIgnores.add(attr);
			}

			UpdateIgnore ug = BeanKit.getAnnoation(entityClass, attr, readMethod, UpdateIgnore.class);
			if (ug != null) {
				checkAttrUpdateIgnores();
				attrUpdateIgnores.add(attr);
			}

			LogicDelete logicDelete = BeanKit.getAnnoation(entityClass, attr, readMethod, LogicDelete.class);
			if (logicDelete != null) {
				setLogicDeleteAttrName(attr);
				setLogicDeleteAttrValue(logicDelete.value());
			}

			Version version = BeanKit.getAnnoation(entityClass, attr, readMethod, Version.class);
			if (version != null) {
				setVersionProperty(attr);
				setInitVersionValue(version.value());
			}

			Column column = BeanKit.getAnnoation(entityClass, attr, readMethod, Column.class);
			if (column != null) {
				String col = column.value();
				attrAnnotationName.put(attr, col);
				colAnnotationName.put(col, attr);
			}

			AutoID autoId = BeanKit.getAnnoation(entityClass, attr, readMethod, AutoID.class);
			if (autoId != null) {
				if (autoIdAttr != null) {
					throw new BeetlSQLException(BeetlSQLException.ANNOTATION_DEFINE_ERROR,
							"@AutoId 应该只有一个，但出现在" + autoIdAttr + " 和 " + attr + " @" + entityClass);
				}
				setAutoIdAttr(attr);
				autoIdAttr = attr;
			}

			SeqID seqId = BeanKit.getAnnotation(entityClass, attr, readMethod, SeqID.class);
			if (seqId != null) {
				if (seqIdAttr != null) {
					throw new BeetlSQLException(BeetlSQLException.ANNOTATION_DEFINE_ERROR,
							"@SeqId 应该只有一个，但出现在" + autoIdAttr + " 和 " + attr + " @" + entityClass);
				}
				setSeqIdAttr(attr);
				seqIdAttr = attr;

			}
			// TODO 这里要将2的AssignID转为3的AssignID
			AssignID assignID = BeanKit.getAnnotation(entityClass, attr, readMethod, AssignID.class);
			if (assignID != null) {
				colAssignID.put(attr, assignID);
			}

			AttributeBuilderHolder holder = BeanKit.getAttributeHanlderHolder(entityClass, attr, p);
			if (holder != null) {
				// 判断是否有对字段特殊处理
				colHandlers.put(p.getName(), holder);
			}

		}

		setAttrInsertIgnores(attrInsertIgnores);
		setAttrUpdateIgnores(attrUpdateIgnores);
		setAttrAnnotationName(attrAnnotationName);
		setColAnnotationName(colAnnotationName);

		makeKeyHolder();
//		Class clz = modifiedClasses.get(entityClass);
//		if (clz == null && !clzSet.contains(entityClass)) {
//			boolean modified = false;
//			DynamicType.Builder bEntityClass = new ByteBuddy().redefine(entityClass);
//			// 动态注入3的AssignID注解
//			if (colAssignID.size() > 0) {
//				modified = true;
//				for (String k : colAssignID.keySet()) {
//					AssignID v = colAssignID.get(k);
//					bEntityClass = bEntityClass.field(ElementMatchers.named(k)).annotateField(
//							AnnotationDescription.Builder.ofType(org.beetl.sql.annotation.entity.AssignID.class)
//									.define("value", v.value()).define("param", v.param()).build());
//				}
//				colAssignID.clear();
//			}
//			
//			Table table = BeanKit.getAnnotation(entityClass, Table.class);
//			if (table != null) {
//				modified = true;
//				bEntityClass = bEntityClass.annotateType(AnnotationDescription.Builder
//						.ofType(org.beetl.sql.annotation.entity.Table.class).define("name", table.name()).build());
//			}
//			
//			if (modified) {
//				clz = bEntityClass.make().load(Thread.currentThread().getContextClassLoader()).getLoaded();
//				setEntityClass(clz);
//				modifiedClasses.put(entityClass, clz);
//				clzSet.add(clz);
//			}
//		}

	}

}
